package com.rljk.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

/**
 * Author:   YASUO
 * Date:     2018/7/23 15:58
 * Description:
 */
public class SignUtil {

    public static String mapToKeyValueStr(Map<String, Object> map) throws Exception {
        StringBuffer content = new StringBuffer();
        boolean first = true;
        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            if (map.get(key) == null) {
                continue;
            }
            Object v = map.get(key);
            if (map.get(key) instanceof String) {
                String s = (String) map.get(key);
                if (s.length() <= 0) {
                    continue;
                }
            } else if (!isBaseDataType(map.get(key).getClass())) {
                if(map.get(key) instanceof JSONArray) {
                    JSONArray js = JSONArray.parseArray(map.get(key).toString());
                    String json = js.toString();
                    v = json;
                } else {
                    JSONObject js = JSONObject.parseObject(map.get(key).toString());
                    String json = js.toString();
                    v = json;
                }
            }

            if (!first) {
                content.append("&").append(key).append("=").append(v);
            } else {
                content.append(key).append("=").append(v);
            }
            first = false;
        }
        return content.toString();
    }

    public static String objToKeyValueStr(Object object) throws Exception {
        Map<String, Object> map = new TreeMap<String, Object>();
        java.beans.PropertyDescriptor pd[] = PropertyUtils.getPropertyDescriptors(object);
        for (int i = 0; i < pd.length; i++) {
            if (pd[i].getReadMethod() != null && pd[i].getWriteMethod() != null) {
                Object value = PropertyUtils.getProperty(object, pd[i].getName());
                if (value != null) {
                    map.put(pd[i].getName(), value);
                }

            }
        }
        return mapToKeyValueStr(map);
    }

    public static Map<String, Object> jsonToMap(JSONObject obj) throws Exception {
        Map<String, Object> map = new TreeMap<String, Object>();
        Iterator<String> keysItr = obj.keySet().iterator();
        while(keysItr.hasNext()) {
            String key = keysItr.next();
            Object value = obj.get(key);
            if(value instanceof JSONArray) {
                value = jsonArrayToKeyPairStr((JSONArray) value);
            } else if(value instanceof JSONObject) {
                value = mapToKeyValueStr(jsonToMap((JSONObject) value));
            }
            map.put(key, value);
        }
        return map;
    }

    public static String jsonArrayToKeyPairStr(JSONArray array) throws Exception {
        List<Object> list = new ArrayList<Object>();
        for(int i = 0; i < array.size(); i++) {
            Object value = array.get(i);
            if(value instanceof JSONArray) {
                value = jsonArrayToKeyPairStr((JSONArray) value);
            } else if(value instanceof JSONObject) {
                value = mapToKeyValueStr(jsonToMap((JSONObject)value));
            }
            list.add(value);
        }
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < list.size() - 1; i++) {
            sb.append(list.get(i).toString()).append(",");
        }
        sb.append(list.get(list.size() - 1));
        return sb.toString();
    }

    /**
     * 判断一个类是否为基本数据类型。
     *
     * @param clazz
     *            要判断的类。
     * @return true 表示为基本数据类型。
     */
    private static boolean isBaseDataType(Class clazz) throws Exception {
        return (clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Byte.class)
                || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class)
                || clazz.equals(Character.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class)
                || clazz.equals(BigInteger.class) || clazz.equals(Boolean.class) || clazz.equals(Date.class) || clazz
                .isPrimitive());
    }



    // 生成签名
    public static String ASCIISort(String characterEncoding, SortedMap<String, Object> parameterMap) {
        if (parameterMap == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        List<String> keys = new ArrayList<>(parameterMap.keySet());
        Collections.sort(keys);

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            // String value = (String) parameters.get(key);
            Object value = parameterMap.get(key);
            // if (Tools.notEmpty(value)) {
            sb.append((i == 0 ? "" : "&") + key + "=" + value);
            // }
        }
        System.out.println("【生成签名   】" + sb.toString());
        return sb.toString();
    }


    // 生成签名
    public static Map ASCIISortToMap(String characterEncoding, SortedMap<String, Object> parameterMap) {
        SortedMap<String, Object> map = new TreeMap<String, Object>();

        if (parameterMap == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        List<String> keys = new ArrayList<>(parameterMap.keySet());
        Collections.sort(keys);

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            // String value = (String) parameters.get(key);
            Object value = parameterMap.get(key);
            // if (Tools.notEmpty(value)) {
            map.put(key,value);
            // }
        }
        System.out.println("【生成签名   】" + map.toString());
        return map;
    }



    /**
     * 将传参按照ASCII 码字典序排序
     * @param map
     * @return
     */
    public static String getSignByMap(Map<String, String> map) {
        String result = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key + ":" + val + ":");
                    }
                }
            }
//			sb.append(PropertyManager.getProperty("SIGNKEY"));
            result = sb.toString();
        } catch (Exception e) {
            return null;
        }
        return result;
    }


    /**
     * 将传参按照ASCII 码字典序排序
     * @param list
     * @return
     */
    public static String getSignByList(ArrayList<String> list) {
        // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        // 构造签名键值对的格式
        StringBuilder sb = new StringBuilder();
        for(String ss:list){
            sb.append(ss+"&");
        }
        return sb.toString();
    }


    /**
     * 将map转换成url
     *
     * @param map
     * @return
     */
    public static String getUrlParamsByMap(Map<String, Object> map) {
        if (map == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            sb.append(entry.getKey() + "=" + entry.getValue());
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StringUtils.substringBeforeLast(s, "&");
        }
        return s;
    }

}
